home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-06-09 | 6.3 KB | 136 lines | [TEXT/MPS ] |
- While devoping Disinfectant I ran into a number of "gotchas" that
- caused me great grief. I thought it would be nice to tell the
- rest of you about these problems, in the hope that you'll be able
- to avoid them in your own programs. I've told DTS about most of this stuff.
-
- Gotcha #1. Watch out for PBGetCatInfo calls with TOPS.
-
- The file manager routine PBGetCatInfo uses a parameter block of type
- CInfoPBRec. Make certain that you pass a pointer to the full parameter
- block when using MPW C, even if you know in advance that the object is a
- directory. Don't just allocate and pass a pointer to the DirInfo variant.
- The DirInfo variant is four bytes shorter than the full union type, and with
- TOPS the PBGetCatInfo call sets those four bytes at the end. If your
- parameter block is not big enough you'll trash the stack.
-
- Gotcha #2. Make certain you're in the proper heap zone before calling
- ReleaseResource.
-
- At the bottom of IM II-26, in the Memory Mangler chapter, is the warning
- "Be sure, when calling routines that access blocks, that the zone in which
- the block is located is the current zone." Heed this warning, especially
- when releasing resources. Bob Hablutzel and I discovered (after hours in
- Macsbug) that on the 128K ROMs, if you try to release an empty (unloaded)
- resource in the system heap, and if you neglect to set the current zone to
- the system zone, then the system will trash the free master pointer list.
- This is not good, and will almost undoubtably lead to subsequent bizarre
- behaviour.
-
- Here's the code I use to release a resource:
-
- curZone = GetZone();
- SetZone(HandleZone(theRez));
- ReleaseResource(theRez);
- SetZone(curZone);
-
- Gotcha #3. Don't believe Inside Macintosh.
-
- On page IM II-34 we read the following warning in the description of the
- HandleZone routine: "If handle h is empty (points to a NIL master pointer),
- HandleZone returns a pointer to the current heap zone." This is false -
- HandleZone properly returns a pointer to the heap zone that contains the
- master pointer. See Gotcha #2 above.
-
- Gotcha #4. Don't expect OpenResFile to do sanity checking.
-
- Neither OpenResFile nor OpenRFPerm does any sanity checking of any sort
- when opening a resource file. If the file is damaged or contains trash it
- is very possible for the Resource Mangler to bomb or hang inside the
- OpenResFile or OpenRFPerm call. Often what happens is that it makes a
- Memory Mangler request for some ridiculously huge block of memory. If you
- have a GrowZone proc this can cause problems.
-
- To prevent this problem you must write a sanity checker of your own that
- opens the resource file as a binary file and checks at least the most
- important structural characteristics of the file. If your sanity check
- fails you must avoid calling OpenResFile or OpenRFPerm on the file. In
- Disinfectant I check that the resource map and resource data are
- within the logical EOF of the file and don't overlap, I check that the
- resource type list immediately follows the resource map, and I check that
- the resource name list starts within the logical eof.
-
- DTS tells me that the only way to be completely safe is to do a complete
- sanity check of the entire resource fork - e.g., rewrite the RezDet MPW
- tool.
-
- Damaged and trashed resource forks are much more common than you might
- think.
-
- Gotcha #5. Don't believe Inside Macintosh.
-
- In the description of the OpenResFile routine, IM I-115 states "If the
- resource file is already open, it doesn't make it the current resource
- file; it simply returns the reference number." This is false. If the
- resource file is already open, OpenResFile in fact DOES make it the
- current resource file. OpenRFPerm also has the same behaviour, in those
- cases where OpenRFPerm returns the reference number of the previously
- opened copy of the file, rather than opening a new access path (see
- IM IV-17 and TN 185).
-
- Gotcha #6. Watch out for Standard File if you unmount volumes.
-
- The standard file package keeps track of the last volume it used in the low
- core global SFSaveDisk, which contains the negative of the vol ref num of
- the last volume used. If your program unmounts this volume and then later
- calls the standard file package again, it will post an alert saying that
- "A system error has occurred. Please try again." A simple fix for this
- problem is to check the vRefNum stored in SFSaveDisk immediately before
- any calls to standard file. Call PBGetVInfo to see if the volume still
- exists. If it doesn't, make an indexed call to PBGetVInfo to get the
- vRefNum of the first volume in the VCB queue, and set SFSaveDisk to the
- negative of this vRefNum. Also set CurDirStore to fsRtDirID.
-
- Gotcha #7. Don't believe Inside Macintosh.
-
- IM I-116 states that "When calling the CurResFile and HomeResFile routines,
- described below, be aware that for the system resource file the actual
- reference number is returned." This is false. CurResFile does indeed
- return the actual reference number of the system file (2), but
- HomeResFile in fact returns 0 for system file resources.
-
- Gotcha #8. Don't believe Inside Macintosh.
-
- IM I-126 states "Like the attributes of individual resources, resource file
- attributes are specified by bits in the low-order byte of a word." This
- is false. In fact, the resource file attributes are stored in the
- high-order byte of the word.
-
- Gotcha #9. Directory IDs are longs, not shorts, stupid.
-
- Directory IDs, unlike volume reference numbers and working directory ids,
- are longs, not shorts. Watch out for this one. It's really easy to
- declare a dirID to be a short by mistake, and unless you're using Modula-2
- you probably won't catch the bug even with extensive beta testing. Don't
- feel too stupid if you do this - I have it on good authority that ResEdit
- once had this bug!
-
- Gotcha #10. Always set the ioNamePtr field in file manager param blocks.
-
- See TN 179. Read it. Believe it. Always set ioNamePtr. Set it to nil
- if you don't care about the name. I made this mistake three times while
- developing Disinfectant, and all three times it took FOREVER to find the
- bug. The problem is those silly little arrows in the file manager
- chapter of IM IV. They all point to the left for ioNamePtr, which usually
- means that you don't have to set the field before calling the routine.
-
- I hope my experiences help somebody.
-
- John Norstad
- Academic Computing and Network Services
- Northwestern University
-
- Bitnet: jln@nuacc
- Internet: jln@acns.nwu.edu
- AppleLink: a0173
- CompuServe: 76666,573
-